#include "DownloadManager.h"
#include "Defines.h"

using namespace std;

size_t WriteFunction(char *data, size_t size, size_t nmemb, DownloadManager *dm)
{
    if (dm == NULL)
        return 0;
    dm->szResource.append(data, size*nmemb);
    if (dm->szResource.size() <= dm->ulMaxFileSize)
        return size*nmemb;
    else
        return 0;
}

size_t HeaderFunction(char *data, size_t size, size_t nmemb, DownloadManager *dm)
{
    if (dm == NULL)
        return 0;
    dm->szResponseHeader.append(data, size*nmemb);
    return size*nmemb;
}

DownloadManager::DownloadManager(void)
{
    ulMaxFileSize = 0;
    ulMaxRedirsCount = 0;

    curlCode = CURLE_OK;
    dSizeDownload = 0;
    dSpeedDownload = 0;
    dTotalTime = 0;
    ulResponseCode = 0;
}

DownloadManager::~DownloadManager(void)
{
}

void DownloadManager::PerformDownload(void)
{
    char *url = NULL;
    curlCode = CURLE_OK;
    szCurlMessage.erase();
    szResource.erase();
    szResponseHeader.erase();
    dSizeDownload = 0;
    dSpeedDownload = 0;
    dTotalTime = 0;
    szEffectiveUrl.erase();
    ulResponseCode = 0;
    
    CURL *curl  = curl_easy_init();
    if (!curl)
    {
        curlCode = CURLE_FAILED_INIT;
        return;
    }

    curlCode = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curlCode = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
    curlCode = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
    curlCode = curl_easy_setopt(curl, CURLOPT_MAXFILESIZE, ulMaxFileSize);
    curlCode = curl_easy_setopt(curl, CURLOPT_MAXREDIRS, ulMaxRedirsCount);
    curlCode = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    curlCode = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteFunction);
    curlCode = curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
    curlCode = curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HeaderFunction);
    curlCode = curl_easy_setopt(curl, CURLOPT_WRITEHEADER, this);
    curlCode = curl_easy_setopt(curl, CURLOPT_URL, szUrl.c_str());
    if (szFormContent.size())
        curlCode = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, szFormContent.c_str());
    if (szCookies.size())
        curlCode = curl_easy_setopt(curl, CURLOPT_COOKIE, szCookies.c_str());
    if (szUserAgent.size())
        curlCode = curl_easy_setopt(curl, CURLOPT_USERAGENT, szUserAgent.c_str());
    if (szReferenceUrl.size())
        curlCode = curl_easy_setopt(curl, CURLOPT_REFERER, szReferenceUrl.c_str());
    else
        curlCode = curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1);
    if (szProxyAddr.size())
        curlCode = curl_easy_setopt(curl, CURLOPT_PROXY, szProxyAddr.c_str());
    if (szProxyAuth.size())
    {
        curlCode = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, szProxyAuth.c_str());
        curlCode = curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
    }
    if (szHttpAuth.size())
    {
        curlCode = curl_easy_setopt(curl, CURLOPT_USERPWD, szHttpAuth.c_str());
        curlCode = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    }    

    curlCode = curl_easy_perform(curl);

    curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dSizeDownload);
    curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &dSpeedDownload);
    curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &dTotalTime);
    curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &ulResponseCode);

    if (url)
        szEffectiveUrl = url;

    if (curlCode == CURLE_PARTIAL_FILE && dSizeDownload > 0 && ulResponseCode == HTTP_STATUS_OK)
        curlCode = CURLE_OK;

    if (curlCode == CURLE_WRITE_ERROR)
        curlCode = CURLE_FILESIZE_EXCEEDED;

    szCurlMessage = curl_easy_strerror(curlCode);

    curl_easy_cleanup(curl);
}
